home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / freeWAIS-sf-1.1 / ir / futil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-13  |  15.9 KB  |  701 lines

  1. /* Wide AREA INFORMATION SERVER SOFTWARE    
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.  
  4.   
  5.    3/90 Brewster
  6. */
  7.  
  8. /* Copyright (c) CNIDR (see ../COPYRIGHT) */
  9.  
  10.  
  11. /* Change log:
  12.  * $Log: futil.c,v $
  13.  * Revision 1.11  1994/12/13  18:52:45  pfeifer
  14.  * chip@chinacat.unicom.com (Chip Rosenthal) patches.
  15.  * Excluding the merge of libinv and libwais
  16.  *
  17.  * Revision 1.10  1994/10/11  14:38:13  pfeifer
  18.  * convex
  19.  *
  20.  * Revision 1.9  1994/08/22  14:09:14  pfeifer
  21.  * jp made getpwuid code safer
  22.  *
  23.  * Revision 1.8  1994/08/05  07:02:43  pfeifer
  24.  * Release beta 04
  25.  *
  26.  * Revision 1.7  1994/07/13  07:53:26  pfeifer
  27.  * beta 02
  28.  *
  29.  * Revision 1.6  1994/06/09  18:31:11  pfeifer
  30.  * added ftp:
  31.  *
  32.  * Revision 1.5  1994/06/09  17:17:32  pfeifer
  33.  * probe_file returns now true for filename = "http:.*"
  34.  *
  35.  * Revision 1.4  1994/05/20  12:55:52  pfeifer
  36.  * beta
  37.  *
  38.  * Revision 1.3  1994/03/08  20:58:57  pfeifer
  39.  * Patchlevel 04
  40.  *
  41.  * Revision 1.2  93/07/01  19:18:02  warnock
  42.  * gethostname -> mygethostname
  43.  * 
  44.  * Revision 1.1  1993/02/16  15:05:35  freewais
  45.  * Initial revision
  46.  *
  47.  * Revision 1.21  92/03/24  10:30:41  jonathan
  48.  * Added fix to pathname_directory if no directory part, it puts "./" in the
  49.  * destination.
  50.  * 
  51.  * Revision 1.20  92/02/21  11:05:48  jonathan
  52.  * added RCSIdent
  53.  * 
  54.  * Revision 1.19  92/02/20  14:51:19  jonathan
  55.  * changed include for access() to sys/file.h, since that seems more portable.
  56.  * 
  57.  * Revision 1.18  92/02/18  11:52:43  jonathan
  58.  * conditionalized inclusion of unistd.h for NeXT (use fcntl instead).  This
  59.  * may be a BSD thing.
  60.  * 
  61.  * Revision 1.17  92/02/12  13:19:27  jonathan
  62.  * Added "$Log" so RCS will put the log message in the header
  63.  * 
  64. */
  65.  
  66. #ifndef lint
  67. static char *RCSid = "$Header: /usr/local/ls6/src+data/src/freeWAIS-sf/ir/RCS/futil.c,v 1.11 1994/12/13 18:52:45 pfeifer Exp $";
  68. #endif
  69.  
  70. /* ======================== */
  71. /* ===  File Utilities  === */
  72. /* ======================== */
  73.  
  74. #include "cdialect.h"
  75. /* #include <string.h> */
  76.  
  77. #ifdef THINK_C
  78.   /* file type info */
  79. #include <pascal.h>        /* for CtoPstr */
  80. #include <FileMgr.h>
  81. #define CREATOR         'WIS1'
  82. #define WAIS_INDEX_FILE_TYPE     'INDX'
  83. #else
  84. /* #include <sys/types.h> /* for stat and getuid */
  85. #include <sys/stat.h> /* for stat */
  86. #include <sys/param.h> /* for getwd */
  87.  
  88. /* for access() */
  89. #include <sys/file.h>
  90. #endif /* THINK_C */
  91.  
  92. #include "futil.h"
  93. #include "panic.h"
  94.  
  95. /*----------------------------------------------------------------------*/
  96.  
  97. static long numFilesCurrentlyOpen = 0;
  98. static long maxNumFilesOpenAtOneTime = 0;
  99.  
  100. FILE*
  101. fs_fopen(fileName,mode)
  102. char* fileName;
  103. char* mode;
  104. {
  105.   FILE* file = NULL;
  106.   char realMode[100];
  107.   
  108. #ifdef BSD
  109. #define implicitBinary
  110. #endif /* def BSD */
  111. #ifdef ultrix
  112. #define implicitBinary
  113. #endif /* def ultrix */
  114. #ifndef ANSI_LIKE
  115. #define implicitBinary
  116. #endif /* def ANSI_LIKE */
  117.  
  118.  
  119.  
  120. #ifdef implicitBinary
  121.    /* these old os's don't handle the binary mode.  Just remove it */
  122.    long i,j;
  123.    for (i = 0L,j = 0; mode[i] != '\0';i++)
  124.     { if (mode[i] != 'b')
  125.     realMode[j++] = mode[i];
  126.     }
  127.    realMode[j] = '\0';
  128.   file = fopen(fileName,realMode);
  129. #else
  130.   file = fopen(fileName,mode);
  131. #endif /* def implicitBinary */
  132.   
  133.   if (file != NULL)
  134.     { numFilesCurrentlyOpen++;
  135.       if (numFilesCurrentlyOpen > maxNumFilesOpenAtOneTime)
  136.     maxNumFilesOpenAtOneTime = numFilesCurrentlyOpen;
  137.     }
  138.   
  139.   return(file);
  140. }
  141.  
  142. /*----------------------------------------------------------------------*/
  143.  
  144. long
  145. fs_fclose(file)
  146. FILE* file;
  147.  
  148. {
  149.   if (file != NULL)
  150.     { numFilesCurrentlyOpen--;
  151.       return(fclose(file));
  152.     }
  153.   else
  154.     return(0L);
  155. }
  156.  
  157. /*----------------------------------------------------------------------*/
  158.  
  159. long fs_fseek(file,offset,wherefrom)
  160. FILE* file;
  161. long offset;
  162. long wherefrom;
  163. {
  164.   long result;
  165.   
  166.   if(NULL == file)
  167.     return -1;
  168.   
  169.   result = fseek(file, offset, wherefrom);
  170.  
  171.   /*
  172.   if(0 != result) 
  173.     panic("A seek failed:  offset %ld, wherefrom %d.\n",offset, wherefrom);
  174.     */
  175.   return result;
  176. }
  177.  
  178. /*----------------------------------------------------------------------*/
  179.  
  180. long fs_ftell(file)
  181. FILE* file;
  182. {
  183.   long result;
  184.   
  185.   if (file == NULL)
  186.     return(0);
  187.     
  188.   result = ftell(file);
  189.   
  190.   if(EOF == result)
  191.     panic("A seek on an index file failed.\n");
  192.  
  193.   return(result);
  194. }
  195.  
  196. /*----------------------------------------------------------------------*/
  197.  
  198. void grow_file(file,length)
  199. FILE* file;
  200. long length;
  201. {
  202.   long current_length;
  203.   s_fseek(file, 0L, SEEK_END);
  204.   current_length = s_ftell(file);
  205.   s_fseek(file, length - current_length, SEEK_END);
  206. }
  207.  
  208. /*----------------------------------------------------------------------*/
  209.  
  210. /* writes the high byte first, this makes reading faster */
  211. long write_bytes(value,size,stream)
  212. long value;
  213. long size;
  214. FILE* stream;
  215. {
  216.   long i;
  217.   long answer;
  218.   if((size < sizeof(long)) && (0 != (value >> (size * 8))))
  219.     panic("In a call to write_bytes, the value %ld can not be represented in %ld bytes", value, size);
  220.   for(i = size - 1; i >= 0; i--){
  221.     answer = putc((value >> (i * 8)) & 0xFF, stream);
  222.   }
  223.   if(ferror(stream) != 0) {
  224.     panic("Write failed");
  225.   }
  226.   return(answer);
  227. }
  228.  
  229. /*----------------------------------------------------------------------*/
  230.  
  231. /* returns EOF if it gets an error */
  232. long read_bytes(n_bytes,stream)
  233. long n_bytes;
  234. FILE *stream;
  235. {
  236.   long answer = 0;
  237.   unsigned long ch;
  238.   long i;
  239.   for(i = 0; i < n_bytes; i++){
  240.     ch = fgetc(stream);
  241.     if(EOF == ch){
  242.       return(EOF);
  243.     }
  244.     answer = (answer << 8) + (unsigned char)ch;
  245.   }
  246.   return(answer);
  247. }
  248.  
  249. /*----------------------------------------------------------------------*/
  250.  
  251. long read_bytes_from_memory(n_bytes,block)
  252. long n_bytes;
  253. unsigned char *block;
  254. {
  255.   long answer = 0;
  256.   unsigned char ch;
  257.   long i;
  258.   for(i = 0; i < n_bytes; i++){
  259.     ch = *(block++);
  260.     answer = (answer << 8) + ch;
  261.   }
  262.   return(answer);
  263. }
  264.  
  265. /*----------------------------------------------------------------------*/
  266.  
  267. time_t file_write_date(filename)
  268. char* filename;
  269. { /* os dependent */
  270. #ifdef THINK_C
  271.     return((time_t)0);  /* not implemented yet */
  272. #else
  273.   struct stat *buf = (struct stat*)s_malloc((size_t)sizeof(struct stat));
  274.   time_t mtime;
  275.  
  276.  
  277.  
  278.    if(0 != stat(filename, buf)) {
  279.      /* might be the compressed one. */
  280.      char buffer[MAX_FILENAME_LEN+2];
  281.      sprintf(buffer, "%s.Z", filename);
  282.      if (0 != stat(buffer, buf)) {
  283.        sprintf(buffer, "%s.gz", filename);
  284.        if (0 != stat(buffer, buf)) {
  285.          panic("could not stat %s", filename);
  286.        }
  287.      }
  288.   }
  289.  
  290.  
  291.   mtime =  buf->st_mtime;
  292.   s_free(buf);
  293.   return(mtime);
  294. #endif /* THINK_C */
  295. }
  296.  
  297. /*----------------------------------------------------------------------*/
  298.  
  299. long file_length(stream)
  300. FILE* stream;
  301. /* return the length (in bytes) of a stream - leave the current
  302.    position where it was
  303.  */ 
  304. {
  305.   long position = ftell(stream);
  306.   long end = -1;
  307.   s_fseek(stream, 0L, SEEK_END);
  308.   end = ftell(stream);    
  309.   s_fseek(stream,position,SEEK_SET);
  310.   return(end);
  311. }
  312.  
  313. /*----------------------------------------------------------------------*/
  314.  
  315. static char *clean_path _AP((char* filename));
  316.  
  317. static char *clean_path(filename)
  318. char *filename;
  319. /* this takes out the '/../' and the '/./' from the path by modifying 
  320.    the argument and returning it. The pathname passed to it must be a 
  321.    full path. This is not optimized. */
  322. {
  323. #ifndef THINK_C
  324.   char *beginning_ptr = strstr(filename, "/../");
  325.   if(NULL != beginning_ptr){
  326.     /* then we have something to process.
  327.        reverse search for the beginning of the last directory,
  328.        in order to snuff it */
  329.     char *ptr;
  330.     for(ptr = beginning_ptr - 1; ptr >= filename; ptr--){
  331.       if(*ptr == '/'){
  332.     /* then we found the beginning of the path */
  333.     strcpy(ptr, beginning_ptr + strlen("/../") -1);
  334.     clean_path(filename);    /* get the other occurances of /../ */
  335.     break;
  336.       }    
  337.     }
  338.   }
  339.   /* now look for /./ */
  340.   beginning_ptr = strstr(filename, "/./");
  341.   if(NULL != beginning_ptr){
  342.     strcpy(beginning_ptr, beginning_ptr + strlen("/./") -1);
  343.     clean_path(filename);    /* get the other occurances of /./ */
  344.   }
  345. #endif                /* ndef THINK_C */
  346.  
  347.   return(filename);
  348.  
  349. }
  350.  
  351. /*----------------------------------------------------------------------*/
  352.     
  353. char *truename(filename,full_path)
  354. char *filename;
  355. char *full_path;
  356. {
  357.   /* this puts into full_path the full pathname including directory.
  358.    */
  359. #ifdef THINK_C
  360.   strcpy(full_path, filename);
  361.   return(full_path); /* do nothing */
  362. #else
  363.   if('/' == filename[0]){
  364.     /* then it is complete already */
  365.     strcpy(full_path, filename);
  366.     clean_path(full_path);
  367.     return(full_path);
  368.   }
  369.   else{
  370. #ifdef HAVE_GETCWD
  371.     getcwd(full_path, MAX_FILENAME_LEN);
  372. #else
  373.     getwd(full_path);
  374. #endif
  375.     s_strncat(full_path,"/",MAX_FILENAME_LEN,MAX_FILENAME_LEN);
  376.     s_strncat(full_path,filename,MAX_FILENAME_LEN,MAX_FILENAME_LEN);
  377.     clean_path(full_path);
  378.     return(full_path);
  379.   }
  380. #endif /* THINK_C */
  381. }
  382.  
  383. /*----------------------------------------------------------------------*/
  384.  
  385. char *pathname_name(pathname)
  386. char *pathname;
  387. /* returns a pointer to the leaf name part of full pathname.
  388.    equivalent to common lisp pathname-name. */
  389. {
  390. #ifdef THINK_C
  391.   char *answer = strrchr(pathname, ':');
  392. #else
  393.   char *answer = strrchr(pathname, '/');
  394. #endif    /* THINK_C */
  395.  
  396.   if(NULL == answer)
  397.     return(pathname);
  398.   return(answer + 1);
  399. }
  400.  
  401. /*----------------------------------------------------------------------*/
  402.  
  403. char *pathname_directory(pathname,destination)
  404. char *pathname;
  405. char *destination;
  406. /* returns a pointer to a string of the directory part of
  407.    the pathname and modifies its destination argument.
  408.    This is the equivalent to the common lisp pathname-directory function. */
  409. {
  410. #ifdef THINK_C
  411.   char *dirptr = strrchr(pathname, ':');
  412. #else
  413.   char *dirptr = strrchr(pathname, '/');
  414. #endif /* THINK_C */
  415.  
  416.   if(NULL == dirptr)
  417. #ifdef THINK_C
  418.     strncpy(destination, pathname, MAX_FILE_NAME_LEN);
  419. #else
  420.     strncpy(destination, "./", MAX_FILENAME_LEN);
  421. #endif /* THINK_C */
  422.   else
  423.     { strncpy(destination, pathname, MAX_FILE_NAME_LEN);
  424.       destination[dirptr - pathname + 1] = '\0';
  425.     }
  426.  
  427.   return(destination);
  428. }
  429.   
  430. /*----------------------------------------------------------------------*/
  431.  
  432. /* Setting the Macintosh File type (requires the MacTraps library) */
  433. /* from Util.c by Harry Morris */
  434.  
  435. #ifdef THINK_C
  436.  
  437. void 
  438. setFileType(fileName,type,creator)
  439. char* fileName;
  440. FType type;
  441. FType creator;
  442.   FInfo info;
  443.   OSErr error;
  444.   
  445.   CtoPstr(fileName);
  446.   error = GetFInfo((StringPtr)fileName,0L,&info);
  447.   if (error != noErr)
  448.     panic("error - Can't get file type of file %s, code %ld\n",
  449.           PtoCstr((char*)fileName),noErr);
  450.   info.fdType = type;
  451.   info.fdCreator = creator;
  452.   error = SetFInfo((StringPtr)fileName,0L,&info);
  453.   if (error != noErr)
  454.     panic("error - Can't change file type of file %s, code %ld\n",
  455.           PtoCstr((char*)fileName),noErr);
  456.   PtoCstr((char*)fileName);
  457. }
  458.  
  459. #endif /* THINK_C */
  460.  
  461. /*----------------------------------------------------------------------*/
  462.  
  463. char *current_user_name()
  464. /* returns the current_user_name as a mail address */
  465. {
  466.   static char answer[200];
  467.   char hostname[120];
  468.   
  469. #ifdef THINK_C
  470.   strcpy(answer,"MAC"); /* could look up the name in the chooser */
  471. #else /* ndef THINK_C */
  472.  
  473. #include <pwd.h>  /* for getpwuid */
  474.  
  475.   struct passwd *pwent = getpwuid(getuid());
  476.  
  477.   if (pwent)
  478.   {
  479.     strncpy(answer, pwent->pw_name, 200);
  480.     strncat(answer, "@", 200);
  481.     mygethostname(hostname, 120);
  482.     strncat(answer, hostname, 200);
  483.   }
  484.   else
  485.     strcpy(answer,"unknown");
  486. #endif /* ndef THINK_C */
  487.  
  488.   return(answer);
  489. }
  490.  
  491. /*----------------------------------------------------------------------*/
  492.  
  493. boolean probe_file(filename)
  494. char *filename;
  495. /* return true if it is there, false otherwise.
  496.    Can this be done faster? 
  497. */
  498. {
  499.   if (!strncmp(filename, "http:", 5)) return(true);
  500.   if (!strncmp(filename, "ftp:", 4)) return(true);
  501.   if (filename == NULL)
  502.     return(false);
  503.   else if (access(filename,R_OK) == 0)
  504.     return(true);
  505.   else
  506.     return(false);
  507. }
  508.  
  509. /*----------------------------------------------------------------------*/
  510.  
  511. boolean probe_file_possibly_compressed(filename)
  512. char *filename;
  513. /* return true if it is there, false otherwise.
  514.    Can this be done faster? */
  515. {
  516.   if (filename == NULL)
  517.     return(false);
  518.   else 
  519.     if (probe_file(filename)) {
  520.       return(true);
  521.     } else {/* try the compression */
  522.       char buffer[ MAX_FILENAME_LEN * 2 ];
  523.       strcpy(buffer, filename);
  524.       strcat(buffer, ".Z");
  525.       if (probe_file(buffer)) {
  526.         return(true);
  527.       } else { /* try the zipp */
  528.         strcpy(buffer, filename);
  529.         strcat(buffer, ".gz");
  530.         return(probe_file(buffer));
  531.       }
  532.     }
  533. }
  534.  
  535. /*----------------------------------------------------------------------*/
  536.  
  537. /* this opens the file for writing (append)p and then closes it again */
  538. boolean touch_file(filename)
  539. char *filename;
  540. /* return false if error, true otherwise. */
  541. {
  542.   FILE *stream = NULL;
  543.   if (filename == NULL)
  544.     return(false);
  545.   stream = s_fopen(filename, "a");
  546.   if (NULL == stream)
  547.     return(false);
  548.   else
  549.     { s_fclose(stream);
  550.       return(true);
  551.     }
  552. }
  553.  
  554. /*----------------------------------------------------------------------*/
  555.  
  556. char *merge_pathnames(pathname, directory)
  557. char *pathname;
  558. char *directory;
  559. {
  560.   /* if the pathname is not complete, then it puts on the directory
  561.      component and returns it in a static variable.  This is Unix specific */
  562.   static char answer[MAX_FILENAME_LEN + 1];
  563.   if((pathname[0] == '/') || (NULL == directory) || directory[0] == '\0')
  564.     return(pathname);
  565.   else{
  566.     answer[0] = '\0';
  567.     strncat(answer, directory, MAX_FILENAME_LEN);
  568. #ifdef THINK_C
  569.     if(directory[strlen(directory) - 1] != ':')
  570.       strncat(answer, ":", MAX_FILENAME_LEN);
  571. #else
  572.     if(directory[strlen(directory) - 1] != '/')
  573.       strncat(answer, "/", MAX_FILENAME_LEN);
  574. #endif
  575.     strncat(answer, pathname, MAX_FILENAME_LEN);
  576.   }
  577.   /* should this call truename? */
  578.   return(answer);
  579. }
  580.  
  581. /*----------------------------------------------------------------------*/
  582.  
  583.  
  584. boolean 
  585. read_string_from_file(stream,array,array_length)
  586. FILE *stream;
  587. char *array;
  588. long array_length;
  589. /* returns true if it wins. */
  590. {
  591.   long ch;
  592.   long char_count = 0;
  593.  
  594.   array[0] = '\0';
  595.   while(true){
  596.     ch = fgetc(stream);
  597.     if(EOF == ch){
  598.       array[char_count] = '\0';
  599.       return(false);
  600.     }
  601.     else if(char_count == array_length){        
  602.       array[char_count] = '\0';
  603.       return(false);
  604.     }
  605.     else if('\0' == ch){
  606.       array[char_count] = '\0';
  607.       return(true);
  608.     }
  609.     else
  610.       array[char_count++] = ch;
  611.   }
  612. }
  613.  
  614. /*----------------------------------------------------------------------*/
  615.  
  616. /* counts the lines in a file */
  617. long count_lines(stream)
  618. FILE *stream;
  619. {
  620.   long answer = 1;
  621.   char line[100];
  622.   fseek(stream, 0L, SEEK_SET);    
  623.   while(NULL != fgets(line,100L,stream))
  624.     answer++;
  625.   return(answer);
  626. }
  627.  
  628.  
  629.  
  630. /*----------------------------------------------------------------------*/
  631.  
  632. #ifndef UNCOMPRESSOR
  633. #define UNCOMPRESSOR "zcat"
  634. #endif
  635. #ifndef UNCOMPRESSOR
  636. #define UNZIPPER "gzcat"
  637. #endif
  638.  
  639. char*
  640. fs_fzcat(fileName)
  641. char *fileName;
  642. /* uncompress the file fileName
  643.    returns a pointer to the name of the uncompressed file if succeeds
  644.    returns NULL if failed
  645. */
  646. {
  647.  
  648.  
  649.   char buffer[ 2 * MAX_FILENAME_LEN + 10 ];
  650.   long err = 0L;
  651.   
  652.  
  653. #if (defined(NeXT) || defined(Mach) || defined(BSD43)) || defined(__convex__)
  654.   char tmpFileName[MAX_FILENAME_LEN+1];
  655. #else
  656.   char *tmpFileName = NULL;
  657. #endif                /* NeXT or Mach */
  658.   char *retptr;
  659.  
  660.   if (fileName == NULL)
  661.     return(NULL);
  662.  
  663. #if defined(NeXT) || defined(Mach) || defined(BSD43) || defined(__convex__)
  664.   tmpnam(tmpFileName);
  665.   retptr = s_strdup(tmpFileName);
  666. #else
  667.   tmpFileName = tempnam("/tmp/", 0);
  668.   retptr = tmpFileName;
  669.   if (! retptr) {
  670.     return(NULL);
  671.   }
  672. #endif
  673.  
  674.  
  675.     strcpy(buffer, fileName);
  676.     strcat(buffer, ".Z");
  677.     if (probe_file(buffer)) {
  678.       sprintf(buffer, "%s %s.Z > %s", UNCOMPRESSOR, fileName, retptr);
  679.     } else {
  680.       sprintf(buffer, "%s %s.gz > %s", UNZIPPER, fileName, retptr);
  681.     }
  682.     system(buffer);
  683.     return(retptr); 
  684.  
  685.  
  686.  
  687. /*   
  688.     if( system(buffer) != 0 ) {
  689.          waislog(WLOG_HIGH, WLOG_ERROR, "Error excuting system command: %s %ld",buffer, err );
  690.     unlink(retptr);
  691.         s_free(retptr);
  692.         return(NULL);
  693.     }
  694.     else {    
  695.        return(retptr);
  696.     }
  697. */
  698.  
  699. }
  700.